package com.example.design.iterator;

import org.springframework.web.client.RestTemplate;

import java.util.*;
import java.util.stream.Collectors;
//迭代器模式具体迭代器
public class EsQueryIterator implements Iterator<Map<String, Object>> {

    //记录当前游标
    private String cursor;
    //记录当前colums,因为只有第一次查询才会返回colums数据
    private List<String> colums;
    //将 ES SQL Rest API 的返回值封装到List<Map>中，以方便处理返回值
    Iterator<Map<String, Object>> iterator;

    RestTemplate restTemplate = new RestTemplate();

    //构造第一次查询，而且初始化我们后续需使用的coulms,iterator,cursor
    public EsQueryIterator(String query, Long fetchSize) {
        EsResponseData esResponseData = restTemplate.postForObject("http://localhost:9200/_sql?format=json",
                new EsSqlQuery(query, fetchSize), EsResponseData.class);
        this.colums = esResponseData.getColumns().stream().map(x -> x.get("name")).collect(Collectors.toList());
        this.iterator = convert(colums, esResponseData).iterator();
    }

    //将 ES SQL Rest API 的返回值封装到List<Map>中，以方便处理返回值
    private List<Map<String, Object>> convert(List<String> colums, EsResponseData esResponseData) {
        List<Map<String, Object>> result = new ArrayList<>();
        for (List<Object> row : esResponseData.getRows()) {
            Map<String, Object> map = new HashMap<>();
            for (int i = 0; i < colums.size(); i++) {
                map.put(colums.get(i), row.get(i));
            }
            result.add(map);
        }
        return result;
    }


    //hastNext根据cursor 是否为空进行后续的第二次第三次的访问，直到cursor为空，返回false
    @Override
    public boolean hasNext() {
        return iterator.hasNext() || scrollNext();
    }

    @Override
    public Map<String, Object> next() {
        return iterator.next();
    }

    //获取第二次及以后的结果
    private boolean scrollNext() {
        if (iterator == null || this.cursor == null) {
            return false;
        }
        EsResponseData esResponseData = restTemplate.postForObject("http://localhost:9200/_sql?format=json", new EsSqlQuery(this.cursor), EsResponseData.class);
        this.cursor = esResponseData.getCursor();
        this.iterator = convert(colums, esResponseData).iterator();
        return iterator.hasNext();
    }
}
